<template>
  <div>
    <Header class="head-perpetual" />
    <div class="perp">
      <div class="perp__head">
        <Market
          :value="pairCode"
          :chain="chainCode"
          :list="tickerList"
          :ticker="ticker"
          :mark-price="markPrice"
          :symbol="symbol"
          @input="emitInput"
        >
          <div class="perp__menu">
            <div class="item">
              <span class="g-clickable" @click="isShowAccount = true"
                >Account</span
              >
            </div>
            <div class="item">
              <span class="g-clickable" @click="isShowDeposit = true"
                >Deposit</span
              >
            </div>
            <div class="item">
              <span class="g-clickable" @click="isShowWithdrawal = true"
                >Withdrawal</span
              >
            </div>
            <div class="item">
              <span class="g-clickable" @click="isShowLeverage = true"
                >Leverage</span
              >
            </div>
            <div class="item">
              <span class="g-clickable" @click="isShowNotifications = true"
                >Notifications</span
              >
            </div>
          </div>
        </Market>
      </div>
      <div class="perp__body">
        <div class="perp__part">
          <Charts
            :key="`${chainCode}${pairCode}`"
            :chain-code="chainCode"
            :pair-code="pairCode"
            :ask-list="askList"
            :bid-list="bidList"
          />
          <div class="transactions">
            <div class="transactions__title">
              <div
                class="item"
                v-for="(item, i) in tabList"
                :key="i"
                :class="{ on: item.code === tab }"
                @click="tab = item.code"
              >
                <span>{{ item.name }}</span>
              </div>
            </div>
            <div class="transactions__list">
              <Positions v-show="tab === '01'" />
              <OpenOrder v-show="tab === '02'" />
              <OrderHistory v-show="tab === '03'" />
              <TradeHistory v-show="tab === '04'" />
              <TransactionHistory v-show="tab === '05'" />
              <Assets v-show="tab === '06'" />
            </div>
          </div>
        </div>
        <div class="perp__part">
          <OrderBook
            :pair-code="pairCode"
            :list="orderList"
            :symbol="symbol"
            @change="priceChange"
            type="01"
            title="Order Book"
          />
          <OrderBook
            :pair-code="pairCode"
            :list="[tradeList]"
            :symbol="symbol"
            class="trades"
            type="02"
            title="Trades"
          />
        </div>
        <div class="perp__part">
          <OrderForm
            :symbol="symbol"
            :pair-code="pairCode"
            :best-price="bestPrice"
            :user-price="userPrice || bestPrice"
            :account-info="accountInfo"
            @showTransfer="showTransfer = true"
            @showLeverage="showLeverage = true"
          />
        </div>
      </div>
    </div>
    <BlurMask close-on-click-modal :visible.sync="isShowAccount">
      <Account @close="isShowAccount = false" />
    </BlurMask>
    <NouDialog close-on-click-modal :visible.sync="isShowLeverage">
      <Leverage @close="isShowLeverage = false" />
    </NouDialog>
    <NouDialog close-on-click-modal :visible.sync="isShowDeposit">
      <Deposit @close="isShowDeposit = false" />
    </NouDialog>
    <NouDialog close-on-click-modal :visible.sync="isShowWithdrawal">
      <Withdrawal @close="isShowWithdrawal = false" />
    </NouDialog>
    <BlurMask close-on-click-modal :visible.sync="isShowNotifications">
      <Notifications @close="isShowNotifications = false" />
    </BlurMask>
  </div>
</template>

<script>
import Header from "@/components/Header";
import Market from "./components/Market";
import Charts from "./components/Charts";
import OrderBook from "./components/OrderBook";
import Trades from "./components/Trades";
import OrderForm from "./components/OrderForm";
import Leverage from "./components/Leverage";
import Deposit from "./components/Deposit";
import Withdrawal from "./components/Withdrawal";
import Account from "./components/Account";
import Notifications from "./components/Notifications";
import BlurMask from "@/components/common/BlurMask";
import NouDialog from "@/components/common/NouDialog";
import Positions from "./components/Transactions/Positions";
import OpenOrder from "./components/Transactions/OpenOrder";
import OrderHistory from "./components/Transactions/OrderHistory";
import TradeHistory from "./components/Transactions/TradeHistory";
import TransactionHistory from "./components/Transactions/TransactionHistory";
import Assets from "./components/Transactions/Assets";
import api from "./components/Charts/components/binance-api";
import { toFixed } from "@/utils/format";

export default {
  components: {
    Header,
    Market,
    Charts,
    OrderBook,
    Trades,
    OrderForm,
    Positions,
    OpenOrder,
    OrderHistory,
    TradeHistory,
    TransactionHistory,
    Assets,
    Leverage,
    Deposit,
    Withdrawal,
    Account,
    Notifications,
    BlurMask,
    NouDialog,
  },
  data() {
    return {
      pairCode: "BTCUSDT",
      tab: "01",
      tabList: [
        {
          code: "01",
          name: "Positions",
        },
        {
          code: "02",
          name: "Open Orders",
        },
        {
          code: "03",
          name: "Order History",
        },
        {
          code: "04",
          name: "Trade History",
        },
        {
          code: "05",
          name: "Transaction History",
        },
        {
          code: "06",
          name: "Assets",
        },
      ],
      isShowLeverage: false,
      isShowDeposit: false,
      isShowWithdrawal: false,
      isShowAccount: false,
      isShowNotifications: false,
      chainCode: localStorage.getItem("walletType") || "eth",
      pairCode: localStorage.getItem("binance_symbol") || "BTCUSDT",
      pairCodeOri: "",
      bestPrice: "",
      userPrice: "",
      exchange: null,
      orderList: [],
      tradeList: [],
      tickerList: [],
      symbolList: [],
      markPrice: {},
      ticker: {},
      exchangeInfo: {},
      accountInfo: {},
      askList: [],
      bidList: [],
      isClaimShowing: false,
      isShowTransactions: false,
      advanceContentClasses: {
        "classic__select-token": true,
        classic__advance: true,
      },
      pricePrecision: 2,
      quantityPrecision: 2,
      priceScaleRegExp: RegExp("^\\d*(\\.?\\d{0,2})"),
      volumeScaleRegExp: RegExp("^\\d*(\\.?\\d{0,2})"),
      timer: null,
    };
  },
  watch: {
    pairCode() {
      this.loadBySymbol();
    },
  },
  computed: {
    symbol() {
      const list = this.symbolList.filter((item) => {
        return item.pair === this.pairCode;
      });
      return list && list[0];
    },
  },
  mounted() {
    this.loadList();
  },
  methods: {
    loadList() {
      api.rest.exchangeInfo().then((res) => {
        const { symbols } = res;
        this.exchangeInfo = res;
        this.symbolList = symbols;
        this.loadBySymbol();
      });

      api.rest.ticker24hr().then((res) => {
        this.tickerList = res;
      });

      const list = [];
      for (var i = 0; i < 17; i++) {
        list.push({
          price: "",
          quantity: "",
        });
      }
      this.orderList = list;
      this.getAccount();
    },
    toPriceFixed(val, _priceScaleRegExp, _pricePrecision) {
      return toFixed(
        val,
        _priceScaleRegExp || this.priceScaleRegExp,
        _pricePrecision || this.pricePrecision
      );
    },
    toVolumeFixed(val, _volumeScaleRegExp, _quantityPrecision) {
      return toFixed(
        val,
        _volumeScaleRegExp || this.volumeScaleRegExp,
        _quantityPrecision || this.quantityPrecision
      );
    },
    loadBySymbol() {
      if (this.pairCodeOri) {
        api.stream.close.ticker(this.pairCodeOri);
        api.stream.close.markPrice(this.pairCodeOri);
        api.stream.close.depthLevel({ symbol: this.pairCodeOri, levels: 20 });
        api.stream.close.aggTrade(this.pairCodeOri);
      }
      this.pairCodeOri = this.pairCode;
      api.stream.markPrice(this.pairCode, (res) => {
        const { price = 0 } = this.markPrice;
        res.indexPrice = +res.indexPrice;
        res.price = +res.price;
        res.red = res.price > price;
        res.green = res.price <= price;
        this.bestPrice = res.price.toFixed(this.symbol.pricePrecision);
        this.markPrice = res;
      });
      api.stream.ticker(this.pairCode, (res) => {
        this.ticker = res;
      });
      api.stream.depthLevel({ symbol: this.pairCode, levels: 20 }, (res) => {
        const { asks, bids } = res;
        const list = JSON.parse(JSON.stringify(this.orderList));
        const _asks = asks
          .sort((a, b) => {
            return a.price > b.price ? 1 : -1;
          })
          .filter((item) => {
            return +item.quantity > 0;
          });
        let sum = 0;
        let size = asks.length > bids.length ? bids.length : asks.length;
        const askList = [];
        for (var i = 0; i < size; i++) {
          const item = _asks[i] || list[i];
          askList.push(item);
        }
        askList.sort((a, b) => {
          return a.price > b.price ? 1 : -1;
        });
        askList.forEach((item, i) => {
          sum += +item.quantity;
          item.sum = sum.toFixed(3);
          item.red = true;
        });
        askList.forEach((item, i) => {
          item.percent = ((item.sum / sum) * 100).toFixed(2) + "%";
          const _item = this.orderList[0][i];
          if (_item && _item.price === item.price && _item.quantity === item.quantity) {
            item.update = 0;
          } else {
            item.update = 1;
          }
        });
        askList.sort((a, b) => {
          return a.price > b.price ? -1 : 1;
        });
        this.askList = JSON.parse(JSON.stringify(askList));
        // mark price
        const { price, indexPrice, red, green } = this.markPrice;
        const mid = {
          mid: true,
          price: price ? price.toFixed(this.symbol.pricePrecision) : "-",
          usdt: indexPrice
            ? indexPrice.toFixed(this.symbol.pricePrecision)
            : "-",
          red,
          green,
          qty: "",
          percent: 0,
        };
        // ask price
        sum = 0;
        const bidSizeIndex = size + 1;
        const _bids = bids
          .sort((a, b) => {
            return a.price > b.price ? -1 : 1;
          })
          .filter((item) => {
            return +item.quantity > 0;
          });
        const bidList = [];
        for (var i = 0; i < size; i++) {
          const item = _bids[i] || list[bidSizeIndex + i];
          bidList.push(item);
        }
        bidList.sort((a, b) => {
          return a.price > b.price ? -1 : 1;
        });
        bidList.forEach((item, i) => {
          sum += +item.quantity;
          item.sum = sum.toFixed(3);
          item.green = true;
        });
        bidList.forEach((item, i) => {
          item.percent = ((item.sum / sum) * 100).toFixed(2) + "%";
          const _item = this.orderList[2][i];
          if (_item && _item.price === item.price && _item.quantity === item.quantity) {
            item.update = 0;
          } else {
            item.update = 1;
          }
          return item;
        });
        this.bidList = JSON.parse(JSON.stringify(bidList));
        this.orderList = [askList].concat([[mid]]).concat([bidList]);
      });
      api.rest.aggTrades({ symbol: this.pairCode, limit: 50 }).then((res) => {
        this.tradeList = res.map((item) => {
          item.red = item.maker;
          item.green = !item.maker;
          return item;
        });
        console.log("trade", this.tradeList);
        api.stream.aggTrade(this.pairCode, (res) => {
          res.red = res.maker;
          res.green = !res.maker;
          this.tradeList.pop();
          this.tradeList.unshift(res);
        });
      });
    },
    async getAccount() {
      clearTimeout(this.timer);
      const user = this.$cookies.get("user") || "";
      if (!user) {
        this.timer = setTimeout(() => {
          this.getAccount();
        }, 10000);
        return;
      }
      try {
        const res1 = await this.$axios.post(
          "/exchange/perpetual/v1/getAccountInfor",
          {
            exchangeCode: "binance",
          }
        );
        const res2 = await this.$axios.post(
          "/exchange/perpetual/v1/getIntrumentParam",
          {
            exchangeCode: "binance",
            instrumentId: "binance_" + this.pairCode,
          }
        );
        const { data } = res1;
        data.instrument = res2.data;
        this.accountInfo = data;
        this.timer = setTimeout(() => {
          this.getAccount();
        }, 10000);
      } catch (e) {
        console.log(e);
      }
    },
    async confirmLeverage(params) {
      try {
        const { leverage, marginType, type } = params;
        if (!type) {
          this.showLeverage = false;
          return;
        }
        let res = null;
        if (type === "02" || type === "03") {
          res = await this.$axios.post("/exchange/perpetual/v1/updMarginType", {
            exchangeCode: "binance",
            instrumentId: "binance_" + this.pairCode,
            marginType: marginType,
          });
          if (!res.error) {
            if (type === "02") {
              showToast("Update Margin Type Success");
              this.showLeverage = false;
              this.getAccount();
              return;
            }
          } else {
            showToast("Update Margin Type Fail");
            return;
          }
        }
        if (type === "01" || type === "03") {
          res = await this.$axios.post("/exchange/perpetual/v1/updLeverage", {
            exchangeCode: "binance",
            instrumentId: "binance_" + this.pairCode,
            leverage: leverage,
          });
          if (!res.error) {
            showToast("Update Leverage Success");
            this.showLeverage = false;
            this.getAccount();
          } else {
            showToast("Update Leverage Fail");
          }
        }
      } catch (e) {
        console.log("confirmLeverage", e);
      }
    },
    async confirmTransfer(params) {
      try {
        const { asset, amount, from, to } = params;
        const res = await this.$axios.post("/exchange/account/v1/transfer", {
          exchangeCode: "binance",
          fromId: "",
          fromAccountType: from,
          toId: "",
          toAccountType: to,
          asset: asset,
          amount: amount,
        });
        const { error } = res;
        if (!error) {
          showToast("Transfer Success");
          this.showTransfer = false;
          this.getAccount();
        } else {
          showToast("Transfer Fail");
        }
      } catch (e) {
        console.log("confirmTransfer", e);
      }
    },
    emitInput(val) {
      this.pairCode = val;
    },
    priceChange(val) {
      this.userPrice = val;
    },
  },
};
</script>

<style lang="scss" scoped>
.perp {
  padding-top: 72px;
  min-height: 100vh;
  box-sizing: border-box;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;

  &__head {
    height: 60px;
    width: 100%;
    background-color: var(--card);
    margin-bottom: var(--card-gap);
    padding: 5px 15px;
    box-sizing: border-box;
    border-radius: 15px;
    position: relative;
  }

  &__body {
    width: 100%;
    flex: 1;
    display: grid;
    grid-gap: var(--card-gap);
    grid-template-columns: 1fr 320px 320px;
  }

  &__part {
    display: flex;
    flex-direction: column;
    padding: 15px;
    border-radius: 15px;
    background-color: var(--card);

    .charts {
      flex: 1;
      margin-bottom: 15px;
    }

    .transactions {
      height: 320px;

      &__title {
        display: flex;
        align-items: center;
        justify-content: flex-start;
        margin: 0 -15px;

        .item {
          cursor: pointer;
          display: flex;
          align-items: center;
          padding: 0 15px 12px 15px;

          &.on {
            span {
              color: var(--color);
            }
          }

          span {
            font-size: 14px;
            font-family: "Roboto Regular";
            white-space: nowrap;
            color: var(--color-content);
          }
        }
      }
    }

    .order-book {
      flex: 1;
      margin-bottom: 5px;
    }

    .trades {
      flex: none;
      margin-bottom: 0;
      height: 320px;
    }
  }

  &__menu {
    display: flex;
    align-items: center;
    justify-content: flex-end;

    .item {
      padding: 0 30px 0 20px;
      height: 30px;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
      cursor: pointer;
      &:hover {
        span {
          color: var(--color);
        }
      }
      span {
        font-size: 14px;
        font-family: "Roboto Medium";
        line-height: 30px;
        color: var(--color-content);
        transition: all 0.3s ease;
      }
      &::before {
        content: "";
        position: absolute;
        right: -5px;
        top: 2px;
        width: 16px;
        height: 16px;
        box-sizing: border-box;
        border-bottom: 1px solid var(--background);
        transform: rotateZ(-70deg) scale(1.414);
        transform-origin: bottom center;
      }

      &:last-child {
        padding-right: 0;
        &::before {
          display: none;
        }
      }
    }
  }
}
</style>
